/**
 * Copyright 2009 Erick Armbrust 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0 
 *   
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */

package tapioca.testing;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import junit.framework.TestCase;
import tapioca.dt.DistributedTransactionEntity;
import tapioca.dt.WrappedDatastoreService;
import tapioca.util.DatastoreStats;
import tapioca.util.DelegateDatastoreService;

import au.com.bytecode.opencsv.CSVWriter;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.dev.LocalDatastoreService;
import com.google.appengine.repackaged.com.google.common.collect.Lists;
import com.google.appengine.tools.development.ApiProxyLocalImpl;
import com.google.apphosting.api.ApiProxy;

/**
 * A JUnit test case used by App Engine datastore tests.
 *
 * @author armbrust@gmail.com (Erick Armbrust)
 */
public class AppEngineTestCase extends TestCase {
  
  protected DatastoreService ds;
  protected Key dummyVersion;
  
  @Override
  public void setUp() throws Exception {
    super.setUp();
    ApiProxyLocalImpl proxy = new ApiProxyLocalImpl(new File(".")) {};
    proxy.setProperty(LocalDatastoreService.NO_STORAGE_PROPERTY, 
        Boolean.TRUE.toString());
    
    ApiProxy.setEnvironmentForCurrentThread(new TestEnvironment());
    ApiProxy.setDelegate(proxy);
    
    ds = new DelegateDatastoreService(DatastoreServiceFactory.getDatastoreService());
    dummyVersion = KeyFactory.createKey(DistributedTransactionEntity.KIND, "dummy");
  }

  @Override
  public void tearDown() throws Exception {
    appendStats(((DelegateDatastoreService) ds).getStats());
    ApiProxy.setDelegate(null);
    ApiProxy.setEnvironmentForCurrentThread(null);
    ds = null;
    dummyVersion = null;
    super.tearDown();
  }
  
  private void appendStats(DatastoreStats stats) {
    String performanceSuffix = System.getProperty("performanceSuffix");
    
    if (performanceSuffix != null && stats.hasGatheredStats()) {
      try {
        String filename = "output" + File.separator + "performance-" + performanceSuffix + ".csv";
        CSVWriter writer = new CSVWriter(new FileWriter(filename, true));
        writer.writeNext(new String[] {
            getName(),
            String.valueOf(stats.getNumGetRequests()), String.valueOf(stats.getNumGetEntities()),
            String.valueOf(stats.getNumPutRequests()), String.valueOf(stats.getNumPutEntities()),
            String.valueOf(stats.getNumDeleteRequests()), String.valueOf(stats.getNumDeleteEntities()),
            String.valueOf(stats.getNumIdAllocations())
        });
        writer.close();
      } catch (IOException e) {
        // Ignore exceptions.
      }
    }
  }
  
  protected Entity createDtEntity(String kind, String value) {
    Entity entity = new Entity(kind);
    entity.setProperty("value", value);
    entity.setProperty(WrappedDatastoreService.WRITE_LOCK_PROPERTY, null);
    entity.setProperty(WrappedDatastoreService.VERSION_PROPERTY, null);
    return entity;
  }

  protected Entity createDtNamedEntity(String kind, String value, String name) {
    Entity entity = new Entity(kind, name);
    entity.setProperty("value", value);
    entity.setProperty(WrappedDatastoreService.WRITE_LOCK_PROPERTY, null);
    entity.setProperty(WrappedDatastoreService.VERSION_PROPERTY, null);
    return entity;
  }  
  
  protected Entity createDtEntityWithParent(String kind, String value, Key parent) {
    Entity entity = new Entity(kind, parent);
    entity.setProperty("value", value);
    entity.setProperty(WrappedDatastoreService.WRITE_LOCK_PROPERTY, null);
    entity.setProperty(WrappedDatastoreService.VERSION_PROPERTY, null);
    return entity;    
  }  
  
  protected Entity createAndSaveDtEntity(String kind, String value) {
    Entity entity = createDtEntity(kind, value);
    entity.setProperty(WrappedDatastoreService.VERSION_PROPERTY, dummyVersion);
    ds.put(entity);
    return entity;
  }

  protected Entity createAndSaveDtNamedEntity(String kind, String value, String name) {
    Entity entity = createDtNamedEntity(kind, value, name);
    Entity pmd = WrappedDatastoreService.createPureMetaData(entity.getKey());
    pmd.setProperty(WrappedDatastoreService.VERSION_PROPERTY, dummyVersion);
    ds.put(Lists.newArrayList(entity, pmd));
    return entity;    
  }  
  
}
